VT-d: fix assertion fault in pci passthrough code
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 13 Jul 2009 10:52:49 +0000 (11:52 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 13 Jul 2009 10:52:49 +0000 (11:52 +0100)
Remove ASSERT(spin_is_locked(&pcidevs_lock)) in
pci_get_pdev_by_domain() to allow caller the flexibility to not hold
the lock if it does not care if the device is hot removed between the
time it got the pdev and the time it is used to get the corresponding
vt-d engine.  In the new RHSA use case, we just wanted to get the vt-d
engine of any device passthrough in the domain. Also, rename RHSA
field "domain" to "proximity domain" to avoid overloading the term
"domain" in virtualization context.

Signed-off-by: Allen Kay <allen.m.kay@intel.com>
xen/drivers/passthrough/pci.c
xen/drivers/passthrough/vtd/dmar.c
xen/drivers/passthrough/vtd/dmar.h
xen/drivers/passthrough/vtd/iommu.c
xen/include/xen/acpi.h

index 0327114fef9a0dcf646daf4acd3959b157c9f262..27699e038ba28b94efa52c648c1b7b88531a8d49 100644 (file)
@@ -89,8 +89,6 @@ struct pci_dev *pci_get_pdev_by_domain(struct domain *d, int bus, int devfn)
 {
     struct pci_dev *pdev = NULL;
 
-    ASSERT(spin_is_locked(&pcidevs_lock));
-
     list_for_each_entry ( pdev, &alldevs_list, alldevs_list )
          if ( (pdev->bus == bus || bus == -1) &&
               (pdev->devfn == devfn || devfn == -1) &&
index 0912c97ff0d4b708faa492f001a2e435bdc3da77..fbbc30204f333693db483612fc280f66f0e53660 100644 (file)
@@ -499,7 +499,7 @@ acpi_parse_one_rhsa(struct acpi_dmar_entry_header *header)
     memset(rhsau, 0, sizeof(struct acpi_rhsa_unit));
 
     rhsau->address = rhsa->address;
-    rhsau->domain = rhsa->domain;
+    rhsau->proximity_domain = rhsa->proximity_domain;
     list_add_tail(&rhsau->list, &acpi_rhsa_units);
 
     return ret;
index 5f78a95f94d126bb0362338d662049fdfb99689f..bed177adc6de7611224fa6e442a15a72b235f416 100644 (file)
@@ -72,7 +72,7 @@ struct acpi_atsr_unit {
 struct acpi_rhsa_unit {
     struct list_head list;
     u64    address;
-    u32    domain;
+    u32    proximity_domain;
 };
 
 #define for_each_drhd_unit(drhd) \
index a0cf9d12d731b82916a7f88ef8ada16d842fd219..608865612df5a4b08db3153d78f53904f387a636 100644 (file)
@@ -143,10 +143,14 @@ u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages)
     struct acpi_rhsa_unit *rhsa;
     struct page_info *pg;
     u64 *vaddr;
+    int node = -1;
 
     rhsa = drhd_to_rhsa(drhd);
+    if ( rhsa )
+        node =  pxm_to_node(rhsa->proximity_domain);
+
     pg = alloc_domheap_pages(NULL, get_order_from_pages(npages),
-                             rhsa ? rhsa->domain : 0);
+                             (node == -1 ) ? 0 : MEMF_node(node));
     if ( !pg )
         return 0;
     vaddr = map_domain_page(page_to_mfn(pg));
@@ -204,6 +208,10 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc)
     ASSERT(spin_is_locked(&hd->mapping_lock));
     if ( hd->pgd_maddr == 0 )
     {
+        /*
+         * just get any passthrough device in the domainr - assume user
+         * assigns only devices from same node to a given guest.
+         */
         pdev = pci_get_pdev_by_domain(domain, -1, -1);
         drhd = acpi_find_matched_drhd_unit(pdev);
         if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) )
index 1023d8106d1e33d4efadc4013ad4818d1293111c..a56d27048fbd7e307b8eb460dd26243ee8f7389e 100644 (file)
@@ -227,7 +227,7 @@ struct acpi_table_atsr {
 
 struct acpi_table_rhsa {
         struct  acpi_dmar_entry_header header;
-        u32     domain;
+        u32     proximity_domain;
         u64     address; /* register base address for this drhd */
 } __attribute__ ((packed));